#include "client.h"
#include "ui_client.h"
#include <QDebug>
#include <QThread>
#include<QDataStream>
#include<QMessageBox>
#include<QDateTime>
#include<QComboBox>
#include<QFont>
#include<QColorDialog>
#include<QFileDialog>
Client::Client(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Client)
{
    ui->setupUi(this);
    this->setWindowTitle("TCP客户端");
    this->setWindowIcon(QIcon(":/Images/1.png"));
    ui->stopButton->setEnabled(false);

    tcpSocket = new QTcpSocket(this);
    connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(receiveMessages()));
    connect(tcpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(mStateChanged(QAbstractSocket::SocketState)));
    connect(&timer,&QTimer::timeout,
                [=]()
        {
            this->timer.stop();//关闭定时器
            sendFileData();
        });
    ui->chooseButton->setEnabled(false);
    ui->sendfileButton->setEnabled(false);//发送按钮变灰
}

Client::~Client()
{
    delete ui;
}

void Client::mStateChanged(QAbstractSocket::SocketState state)
{
    switch (state) {
    case QAbstractSocket::UnconnectedState:
        ui->receive->append("客户端：与服务端断开连接");
        ui->connectButton->setEnabled(true);
        ui->stopButton->setEnabled(false);
        break;
    case QAbstractSocket::ConnectedState:
        ui->receive->append("客户端：已连接服务端");
        ui->connectButton->setEnabled(false);
        ui->stopButton->setEnabled(true);
        ui->chooseButton->setEnabled(true);
        break;
    default:
        break;
    }
}

void Client::receiveMessages()
{
    // 接收消息
    QByteArray array = tcpSocket->readAll();
    QDataStream stream(&array,QIODevice::ReadOnly);
    QString type,name;

    stream>>type>>name;
    time=QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");

    if(type == "0") {
        QColor color;
        color.setRgb(0,173, 216, 230);
        ui->receive->setTextColor(color);
        ui->receive->append("["+name+"]"+time);
        color.setRgb(215, 215, 215);
        ui->receive->setTextColor(color);
        QString msg;
        stream >> msg;
        ui->receive->append(msg);
    } else if(type == '1') {
        QColor color;
        color.setRgb(0,173, 216, 230);
        ui->receive->setTextColor(color);
        ui->receive->append("["+name+"]"+time);
        color.setRgb(215, 215, 215);
        ui->receive->setTextColor(color);
        QString msg;
        stream >> msg;
        ui->proBar->setVisible(true);
        isFile = true;
        fileName = msg.section("#",1,1);
        //文件大小
        fileSize = msg.section("#",2,2).toInt();
        qDebug() << fileName << fileSize;

        QString path = ui->path->text();
        path.append(fileName);
        recvSize = 0;
        file = new QFile(path);

        if(!file->open(QIODevice::WriteOnly)){
            //初始化数据
            fileName = "";
            fileSize = 0;
            recvSize = 0;
            isFile = false;
            QMessageBox::warning(this,"警告","创建文件失败");
            return;
        }

        //设置进度条最大值最小值
        ui->proBar->setMinimum(0);
        ui->proBar->setMaximum(fileSize/1024);

        ui->receive->append(QString("正在接受文件：\n%1").arg(fileName));

    } else if(type == '2'){
        QByteArray msg;
        stream >> msg;
        qint64 len = file->write(msg);
        recvSize += len;
        qDebug() << len;
        ui->proBar->setValue(recvSize/fileSize);
    }

    if (recvSize == fileSize){
        file->close();  //接收完毕后关闭文件
        //重置相关变量
        ui->proBar->setValue(0);
        ui->proBar->setVisible(false);
        fileName = "";
        recvSize = 0;
        QMessageBox::information(this,"ok","文件接受完毕");
        ui->chooseButton->setEnabled(true);
     }

}


void Client::on_sendButton_clicked()
{
    time=QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
    QColor color;
    color.setRgb(0,173, 216, 230);
    ui->receive->setTextColor(color);
    ui->receive->append("[客户端" + ui->nameEdit->text()+"]"+time);
    color.setRgb(215, 215, 215);
    ui->receive->setTextColor(color);
    QString type = "0";
    // 发送消息
    if (tcpSocket->state() == QAbstractSocket::ConnectedState) {
        QString x = getMsg();
        QByteArray array;
        QDataStream stream(&array,QIODevice::WriteOnly);
        stream << type << "客户端" + ui->nameEdit->text() << x;
        tcpSocket->write(array);
        ui->receive->append(x);
    } else
        ui->receive->append("请先与服务端连接！");
}

void Client::on_connectButton_clicked()
{
    ui->receive->append("客户端:监听的ip地址:" + ui->ip->text().toUtf8()+ "端口：" + ui->port->text());
    // 连接服务端，指定服务端的ip地址与端口
    tcpSocket->connectToHost(QHostAddress(ui->ip->text()), ui->port->text().toUInt());

    QByteArray array;
    QDataStream stream(&array,QIODevice::WriteOnly);
     stream << "客户端" +ui->nameEdit->text()+ "加入聊天";
    tcpSocket->write(array);

    time=QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
    QColor color;
    color.setRgb(0,173, 216, 230);
    ui->receive->setTextColor(color);
    ui->receive->append(time);
    color.setRgb(215, 215, 215);
    ui->receive->setTextColor(color);
}

void Client::on_stopButton_clicked()
{
    time=QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
    QColor color;
    color.setRgb(0,173, 216, 230);
    ui->receive->setTextColor(color);
    ui->receive->append(time);
    color.setRgb(215, 215, 215);
    ui->receive->setTextColor(color);


    // 断开连接
    tcpSocket->disconnectFromHost();
}

QString Client::getMsg()
{
    QString msg = ui->send->toHtml();
    ui->send->clear();
    ui->send->setFocus();
    return msg;
}
void Client::on_chooseButton_clicked() {
    QString path = QFileDialog::getOpenFileName(this,"请选择所要发送的文件","../");
    if(!path.isEmpty())
    {
            file = new QFile(path);
            //只读方式打开文件
            bool isOk = file->open(QIODevice::ReadOnly);
            if(!isOk)//打开文件失败
            {
                QMessageBox::warning(this,"警告","打开文件失败");
                return;
            }
            else
            {
                ui->receive->append("发送的文件：");
                ui->receive->append(path);

                //初始化数据
                fileName = "";
                fileSize = 0;
                sendSize = 0;

                //获取发送文件的信息
                QFileInfo info(path);
                fileName = info.fileName();
                fileSize = info.size();

                ui->sendfileButton->setEnabled(true);//恢复发送文件按钮
                ui->chooseButton->setEnabled(false);//选择按钮变灰
            }
    }
}
void Client::on_sendfileButton_clicked() {
     ui->sendfileButton->setEnabled(false);
     ui->proBar->setVisible(true);
     ui->proBar->setMinimum(0);
     ui->proBar->setMaximum(fileSize/1024);
     //先发送文件头，自定义的数据，不是文件数据
     //先发送头。自定义组包， 文件名#文件大小
     QString buf = QString("#%1#%2").arg(fileName).arg(fileSize);
     QString type = "1";
     QByteArray array;
     QDataStream stream(&array,QIODevice::WriteOnly);
     stream << type << ui->nameEdit->text() << buf;
     //先发头
     qint64 len = tcpSocket->write(array);
     tcpSocket->waitForBytesWritten();//等待数据发送完毕

     QColor color;
     color.setRgb(0,173, 216, 230);
     ui->receive->setTextColor(color);
     ui->receive->append("[客户端"+ui->nameEdit->text()+"]"+time);
     color.setRgb(215, 215, 215);
     ui->receive->setTextColor(color);
     ui->receive->append("已经在发送文件！！");

     if(len>0)//如果头部信息发送成功，开始发送文件数据
     {
         //10毫秒后在发送文件数据
         //启动定时器，定时器内容发送文件数据
         //防止tcp黏包问题
         this->timer.start(1000);//为了延时
     }
     else
     {
         file->close();
     }
}

void Client::sendFileData() {
    QString type = "2";
    qint64 len = 0 ;
    while(true){
        //每次发送20kb大小的数据，如果剩余的数据不足1kb，就发送剩余数据的大小
        QByteArray buf;
        buf = file->read(qMin(max,fileSize - sendSize));       //读数据
        if(sendSize != fileSize) {
            QByteArray array;
            QDataStream stream(&array,QIODevice::WriteOnly);
            stream << type << ui->nameEdit->text() << buf;
            tcpSocket->write(array);            //发数据
            tcpSocket->waitForBytesWritten();
            len = buf.size();
            //发送数据长度需要累积
            sendSize += len;
            qDebug() << len;
        }else break;
        QThread::msleep(100);
    }

    //文件数据发送完毕
    if (fileSize == sendSize) {
        ui->receive->append("发送成功");
    }

    file->close();//关闭文件
    sendSize = 0;
    ui->chooseButton->setEnabled(true);
    ui->proBar->setValue(0);
    ui->proBar->setVisible(false);
}

void Client::on_underlineTbtn_clicked() {
    underline = !underline;

    ui->send->setFontUnderline(underline);
    ui->send->setFocus();
}
void Client::on_boldBtn_clicked() {
    bold = !bold;
    if(bold){
       ui->send->setFontWeight(QFont::Bold);
    }else{
        ui->send->setFontWeight(QFont::Normal);
    }
}
void Client::on_clearTbtn_clicked() {
    ui->receive->clear();
}
void Client::on_colorTbtn_clicked() {
    QColor color=QColorDialog::getColor(color,this);
     ui->send->setTextColor(color);
}
void Client::on_italicTbtn_clicked() {
    italic = !italic;
    ui->send->setFontItalic(italic);
    ui->send->setFocus();
}
void Client::on_saveTbtn_clicked() {
    if(ui->receive->toPlainText().isEmpty()){
        QMessageBox::warning(this,"警告","保存内容不能为空");
        return;
    }
    //获取保存文件绝对路径/文件名(窗口标题,文件名,类型)
    QString fileName=QFileDialog::getSaveFileName(this,"保存聊天记录","聊天记录","(*.txt)");
    if(!fileName.isEmpty()){
        QFile file(fileName);
        file.open(QIODevice::WriteOnly|QFile::Text);
        QTextStream stream(&file);
        stream<<ui->receive->toPlainText();
        file.close();
    }
}
void Client::on_fontcbx_currentFontChanged()
{
    ui->send->setFontFamily(ui->fontcbx->currentText());
    ui->send->setFocus();
}
void Client::on_sizeCbx_currentTextChanged()
{

    ui->send->setFontPointSize(ui->sizeCbx->currentText().toUInt());
    ui->send->setFocus();
}

